package repository

import (
	"context"
	"errors"

	"gorm.io/gorm"

	"BookStack/internal/domain/article"
	appErrors "BookStack/pkg/errors"
)

// articleRepository 文章仓储实现
type articleRepository struct {
	db *gorm.DB
}

// NewArticleRepository 创建文章仓储
func NewArticleRepository(db *gorm.DB) article.Repository {
	return &articleRepository{
		db: db,
	}
}

// Create 创建文章
func (r *articleRepository) Create(ctx context.Context, a *article.Article) error {
	return r.db.WithContext(ctx).Create(a).Error
}

// GetByID 根据ID获取文章
func (r *articleRepository) GetByID(ctx context.Context, id uint) (*article.Article, error) {
	var a article.Article
	if err := r.db.WithContext(ctx).First(&a, id).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, appErrors.New(appErrors.ErrCodeArticleNotFound, "")
		}
		return nil, err
	}
	return &a, nil
}

// GetBySlug 根据Slug获取文章
func (r *articleRepository) GetBySlug(ctx context.Context, slug string) (*article.Article, error) {
	var a article.Article
	if err := r.db.WithContext(ctx).Where("slug = ?", slug).First(&a).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, appErrors.New(appErrors.ErrCodeArticleNotFound, "")
		}
		return nil, err
	}
	return &a, nil
}

// List 获取文章列表
func (r *articleRepository) List(ctx context.Context, offset, limit int, filters map[string]interface{}) ([]*article.Article, int64, error) {
	var articles []*article.Article
	var total int64

	query := r.db.WithContext(ctx).Model(&article.Article{})

	// 应用过滤条件
	for key, value := range filters {
		query = query.Where(key, value)
	}

	// 查询总数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 分页查询
	if err := query.Offset(offset).Limit(limit).Find(&articles).Error; err != nil {
		return nil, 0, err
	}

	return articles, total, nil
}

// ListByAuthor 获取作者的文章列表
func (r *articleRepository) ListByAuthor(ctx context.Context, authorID uint, offset, limit int) ([]*article.Article, int64, error) {
	var articles []*article.Article
	var total int64

	// 查询总数
	if err := r.db.WithContext(ctx).Model(&article.Article{}).Where("author_id = ?", authorID).Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 分页查询
	if err := r.db.WithContext(ctx).Where("author_id = ?", authorID).Offset(offset).Limit(limit).Find(&articles).Error; err != nil {
		return nil, 0, err
	}

	return articles, total, nil
}

// ListByCategory 获取分类下的文章列表
func (r *articleRepository) ListByCategory(ctx context.Context, categoryID uint, offset, limit int) ([]*article.Article, int64, error) {
	var articles []*article.Article
	var total int64

	// 查询总数
	if err := r.db.WithContext(ctx).Model(&article.Article{}).Where("category_id = ?", categoryID).Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 分页查询
	if err := r.db.WithContext(ctx).Where("category_id = ?", categoryID).Offset(offset).Limit(limit).Find(&articles).Error; err != nil {
		return nil, 0, err
	}

	return articles, total, nil
}

// ListRecommended 获取推荐文章列表
func (r *articleRepository) ListRecommended(ctx context.Context, offset, limit int) ([]*article.Article, int64, error) {
	var articles []*article.Article
	var total int64

	// 查询总数
	if err := r.db.WithContext(ctx).Model(&article.Article{}).Where("is_recommend = ?", true).Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 分页查询
	if err := r.db.WithContext(ctx).Where("is_recommend = ?", true).Offset(offset).Limit(limit).Find(&articles).Error; err != nil {
		return nil, 0, err
	}

	return articles, total, nil
}

// Update 更新文章
func (r *articleRepository) Update(ctx context.Context, a *article.Article) error {
	return r.db.WithContext(ctx).Save(a).Error
}

// Delete 删除文章
func (r *articleRepository) Delete(ctx context.Context, id uint) error {
	return r.db.WithContext(ctx).Delete(&article.Article{}, id).Error
}

// ExistsByTitle 检查标题是否存在
func (r *articleRepository) ExistsByTitle(ctx context.Context, title string, excludeID uint) (bool, error) {
	var count int64
	query := r.db.WithContext(ctx).Model(&article.Article{}).Where("title = ?", title)

	// 如果排除特定ID
	if excludeID > 0 {
		query = query.Where("id != ?", excludeID)
	}

	if err := query.Count(&count).Error; err != nil {
		return false, err
	}
	return count > 0, nil
}

// ExistsBySlug 检查Slug是否存在
func (r *articleRepository) ExistsBySlug(ctx context.Context, slug string, excludeID uint) (bool, error) {
	var count int64
	query := r.db.WithContext(ctx).Model(&article.Article{}).Where("slug = ?", slug)

	// 如果排除特定ID
	if excludeID > 0 {
		query = query.Where("id != ?", excludeID)
	}

	if err := query.Count(&count).Error; err != nil {
		return false, err
	}
	return count > 0, nil
}

// IncrementViews 增加文章浏览量
func (r *articleRepository) IncrementViews(ctx context.Context, id uint) error {
	return r.db.WithContext(ctx).Model(&article.Article{}).Where("id = ?", id).
		UpdateColumn("views", gorm.Expr("views + ?", 1)).Error
}

// IncrementLikes 增加文章点赞数
func (r *articleRepository) IncrementLikes(ctx context.Context, id uint) error {
	return r.db.WithContext(ctx).Model(&article.Article{}).Where("id = ?", id).
		UpdateColumn("likes", gorm.Expr("likes + ?", 1)).Error
}

// DecrementLikes 减少文章点赞数
func (r *articleRepository) DecrementLikes(ctx context.Context, id uint) error {
	return r.db.WithContext(ctx).Model(&article.Article{}).Where("id = ?", id).
		Where("likes > 0").
		UpdateColumn("likes", gorm.Expr("likes - ?", 1)).Error
}

// IncrementComments 增加文章评论数
func (r *articleRepository) IncrementComments(ctx context.Context, id uint) error {
	return r.db.WithContext(ctx).Model(&article.Article{}).Where("id = ?", id).
		UpdateColumn("comments", gorm.Expr("comments + ?", 1)).Error
}

// DecrementComments 减少文章评论数
func (r *articleRepository) DecrementComments(ctx context.Context, id uint) error {
	return r.db.WithContext(ctx).Model(&article.Article{}).Where("id = ?", id).
		Where("comments > 0").
		UpdateColumn("comments", gorm.Expr("comments - ?", 1)).Error
}
